//
//  XLSHAUtils.m
//  XLCryptoTool
//
//  Created by ilongge on 2022/8/16.
//

#import "XLSHAUtils.h"

@implementation XLSHAUtils

+ (NSString *)shaCryptoWithMode:(XL_SHA_Crypto_Mode)cryptoMode
                     andKeyMode:(XL_SHA_Key_Mode)keyMode
                         andKey:(NSString *)encryptKey
                        andText:(NSString *)text
{
    NSMutableString *cryptoString;
    unsigned char cryptoArray[cryptoMode];
    switch (keyMode) {
        case XL_SHA_Key_Mode_HMAC:
        {
            const char *cKey  = [encryptKey UTF8String];
            const char *cData = [text UTF8String];
            switch (cryptoMode) {
                case CC_SHA1_DIGEST_LENGTH:
                    CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cryptoArray);
                    break;
                case CC_SHA224_DIGEST_LENGTH:
                    CCHmac(kCCHmacAlgSHA224, cKey, strlen(cKey), cData, strlen(cData), cryptoArray);
                    break;
                case CC_SHA256_DIGEST_LENGTH:
                    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cryptoArray);
                    break;
                case CC_SHA384_DIGEST_LENGTH:
                    CCHmac(kCCHmacAlgSHA384, cKey, strlen(cKey), cData, strlen(cData), cryptoArray);
                    break;
                case CC_SHA512_DIGEST_LENGTH:
                    CCHmac(kCCHmacAlgSHA512, cKey, strlen(cKey), cData, strlen(cData), cryptoArray);
                    break;
                default:
                    break;
            }
            NSData *cryptoData = [NSData dataWithBytes:cryptoArray length:sizeof(cryptoArray)];
            const unsigned char *buffer = (const unsigned char *)[cryptoData bytes];
            cryptoString = [NSMutableString stringWithCapacity:cryptoData.length * 2];
            for (int i = 0; i < cryptoMode; ++i){
                [cryptoString appendFormat:@"%02x", buffer[i]];
            }
        }
            break;
        case XL_SHA_Key_Mode_Salt_Front:
        {
            NSString *saltString = [NSString stringWithFormat:@"%@%@", encryptKey.length?encryptKey:@"", text];
            const char *saltData = [saltString UTF8String];
            switch (cryptoMode) {
                case CC_SHA1_DIGEST_LENGTH:
                    CC_SHA1(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                case CC_SHA224_DIGEST_LENGTH:
                    CC_SHA224(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                case CC_SHA256_DIGEST_LENGTH:
                    CC_SHA256(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                case CC_SHA384_DIGEST_LENGTH:
                    CC_SHA384(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                case CC_SHA512_DIGEST_LENGTH:
                    CC_SHA512(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                default:
                    break;
            }
            cryptoString = [NSMutableString stringWithCapacity:cryptoMode * 2];
            for(int i = 0; i < cryptoMode; i++)
            {
                [cryptoString appendFormat:@"%02x", cryptoArray[i]];
            }
        }
            break;
        case XL_SHA_Key_Mode_Salt_Behind:
        {
            NSString *saltString = [NSString stringWithFormat:@"%@%@", text, encryptKey.length?encryptKey:@""];
            const char *saltData = [saltString UTF8String];
            switch (cryptoMode) {
                case CC_SHA1_DIGEST_LENGTH:
                    CC_SHA1(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                case CC_SHA224_DIGEST_LENGTH:
                    CC_SHA224(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                case CC_SHA256_DIGEST_LENGTH:
                    CC_SHA256(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                case CC_SHA384_DIGEST_LENGTH:
                    CC_SHA384(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                case CC_SHA512_DIGEST_LENGTH:
                    CC_SHA512(saltData, (CC_LONG)strlen(saltData), cryptoArray);
                    break;
                default:
                    break;
            }
            cryptoString = [NSMutableString stringWithCapacity:cryptoMode * 2];
            for(int i = 0; i < cryptoMode; i++)
            {
                [cryptoString appendFormat:@"%02x", cryptoArray[i]];
            }
        }
            break;
        default:
            break;
    }
    return cryptoString;
}

@end
